﻿<!doctype html>
<html lang="en">
<head>
	<meta charset="utf-8">

	<title>Fetch Tester</title>
	<meta name="description" content="Fetch Tester 3000 allows you to write fetch statements and get formatted results, a JCL ready version, and much more">
	<meta name="author" content="Paul Way, Justin Hamlin">
	<meta http-equiv="X-UA-Compatible" content="IE=10" />


    <link rel=stylesheet href="codemirror/doc/docs.css">

    <link rel="stylesheet" href="codemirror/lib/codemirror.css">
    <link rel="stylesheet" href="codemirror/addon/hint/show.css">
    <script src="codemirror/lib/codemirror.js"></script>
    <script src="codemirror/addon/hint/show.js"></script>
    <script src="codemirror/addon/hint/xml.js"></script>
    <script src="codemirror/mode/xml/xml.js"></script>



	<link rel="stylesheet" href="style/bootstrap.css" />
	<link rel="stylesheet" href="style/ft3.css" />

	<!-- Context -->
    <script type="text/javascript" src="../ClientGlobalContext.js.aspx"></script>

	<script src="script/jquery.2.1.0.js"></script>
	<script src="script/vkbeautify.0.99.00.beta.js"></script>
	<script src="script/jcl.js"></script>
	<script src="script/bootstrap.min.js"></script>
	<script src="script/xmllint.js"></script>

	<script type="text/javascript">

		var formatter = {};	

		formatter.formatXMLForJCL = function (code) {
			return code.replace(/\'/g, '\"').replace(/\</g, '&lt;').replace(/\>/g, '&gt;');
		};
	
		formatter.syntaxHighlight = function (json) {
		    if (typeof json != 'string') {
		         json = JSON.stringify(json, undefined, 2);
		    }
		    json = json.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
		    return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
		        var cls = 'number';
		        if (/[a-fA-F0-9]{8}-([a-fA-F0-9]{4}-){3}[a-fA-F0-9]{12}/.test(match)) {
		        	cls = 'guid';
		        } else if (/^"/.test(match)) {
		            if (/:$/.test(match)) {
		                cls = 'key';
		            } else {
		                cls = 'string';
		            }
		        } else if (/true|false/.test(match)) {
		            cls = 'boolean';
		        } else if (/null/.test(match)) {
		            cls = 'null';
		        }
		        
		        return '<span class="' + cls + '">' + match + '</span>';
		    });
		};

		formatter.syntaxHighlightJS = function (json) {
			return json = json.replace(/(\/\/.+)|('.+')|(&quot;.+&quot;)|(var)|([+=])|(if)|(else)|(typeof)|(function)|(alert)|(length)|(attributes)|(".+")/g, function (match) {
				var cls = '';
				if (/\/\/.+/.test(match)) {
					cls = 'comment';
				} else if (/('.+')|(&quot;.+&quot;)|(".+")/.test(match)) {
					cls = 'string';
				} else if (/(var)|([+=])|(if)|(else)|(typeof)|(function)/.test(match)) {
					cls = 'reserved';
				} else if (/(alert)|(length)|(attributes)/.test(match)) {
					cls = 'props';
				}

				if (cls == '') {
					return match;
				} else {
					return '<span class="' + cls + '">' + match + '</span>';
				}
			});
			//return json;
		};
    
    var validator = {};
    
    validator.Crm2013Xsd = '<?xml version="1.0" encoding="utf-8" ?><xs:schema id="fetch" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema" 	xmlns:mstns="http://tempuri.org/fetch/unique"><xs:annotation><xs:documentation>Schema name: fetch-schema</xs:documentation></xs:annotation><!-- 		condition element - used for capturing entity and link-entity	"where" clause criteria	 	--><!-- [XDR-XSD] "value" element  --><xs:element name="value" type="xs:string"></xs:element><!-- [XDR-XSD] "condition" element  --><xs:element name="condition"><xs:complexType><xs:choice minOccurs="0" maxOccurs="unbounded"><!-- --><!--	The attribute "value" is used for all operators that compare to a single value (for example, eq).	The element "value" is used for operators that compare to multiple values (for example, in).	Some operators require neither the attribute "value" or the element "value" (for example, null). 	--><xs:element name="value" minOccurs="0" maxOccurs="unbounded"><xs:complexType><xs:simpleContent><xs:extension base="xs:string"><xs:attribute name="uiname" type="xs:string" /><xs:attribute name="uitype" type="xs:string" /></xs:extension></xs:simpleContent></xs:complexType></xs:element></xs:choice><!-- --><xs:attribute name="column" type="xs:string" /><xs:attribute name="attribute" type="xs:string"></xs:attribute><xs:attribute name="entityname" type="xs:string"></xs:attribute><xs:attribute name="operator" use="required" type="operator"></xs:attribute><!--	The attribute "value" is used for all operators that compare to a single value (for example, eq).	The element "value" is used for operators that compare to multiple values (for example, in).	Some operators require neither the attribute "value" or the element "value" (for example, null). 	--><xs:attribute name="value" type="xs:string"></xs:attribute><xs:attribute name="aggregate" type="AggregateType"></xs:attribute><xs:attribute name="alias" type="xs:string"></xs:attribute><xs:attribute name="uiname" /><xs:attribute name="uitype" /><xs:attribute name="uihidden" type="TrueFalse01Type" /></xs:complexType></xs:element><!-- 		filter element - used for constructing complex conditionals legal on entity and link-entity	 	--><!-- [XDR-XSD] "filter" element  --><xs:element name="filter"><xs:complexType><xs:choice minOccurs="0" maxOccurs="unbounded"><!-- --><xs:element ref="condition" minOccurs="0" maxOccurs="500" /><xs:element ref="filter" minOccurs="0" maxOccurs="unbounded" /></xs:choice><!-- --><xs:attribute name="type" default="and"><xs:simpleType><xs:restriction base="xs:NMTOKEN"><xs:enumeration value="and" /><xs:enumeration value="or" /></xs:restriction></xs:simpleType></xs:attribute><xs:attribute name="isquickfindfields" type="xs:boolean" /></xs:complexType></xs:element><!-- 		attribute elements - used for selecting attributes from the surrounding entity / link-entity, these values are returned as part of the fetch	 	--><!-- [XDR-XSD] "all-attributes" element  --><xs:element name="all-attributes"><xs:complexType></xs:complexType></xs:element><!-- [XDR-XSD] "attribute" element  --><xs:complexType name="FetchAttributeType"><xs:attribute name="name" use="required" type="xs:string"></xs:attribute><xs:attribute name="build" type="build"></xs:attribute><xs:attribute name="addedby" type="xs:string" /><xs:attribute name="alias" type="xs:string"></xs:attribute><xs:attribute name="aggregate" type="AggregateType"></xs:attribute><xs:attribute name="groupby" type="FetchBoolType"></xs:attribute><xs:attribute name="dategrouping" type="DateGroupingType"></xs:attribute><xs:attribute name="usertimezone" type="FetchBoolType"></xs:attribute></xs:complexType><!-- 	 	order element - used to specify a sort order 	--><!-- [XDR-XSD] "order" element  --><xs:complexType name="FetchOrderType"><xs:choice minOccurs="0" maxOccurs="unbounded"><!-- --></xs:choice><!-- --><xs:attribute name="attribute" type="xs:string"></xs:attribute><xs:attribute name="alias" type="xs:string"></xs:attribute><xs:attribute name="descending" default="false" type="xs:boolean"></xs:attribute></xs:complexType><!-- 		link-entity element - used for joining one entity to its "parent"	 	--><!-- [XDR-XSD] "link-entity" element  --><xs:complexType name="FetchLinkEntityType"><xs:choice minOccurs="0" maxOccurs="unbounded"><!-- --><xs:element ref="all-attributes" minOccurs="0" /><xs:element name="attribute" type="FetchAttributeType" minOccurs="0" maxOccurs="unbounded" /><xs:element name="order" type="FetchOrderType" minOccurs="0" maxOccurs="1" /><xs:element ref="filter" minOccurs="0" /><xs:element name="link-entity" type="FetchLinkEntityType" /></xs:choice><!-- --><xs:attribute name="name" use="required" type="xs:string"></xs:attribute><xs:attribute name="to" type="xs:string"></xs:attribute><xs:attribute name="from" type="xs:string"></xs:attribute><xs:attribute name="alias" type="xs:string"></xs:attribute><xs:attribute name="link-type" type="xs:string"></xs:attribute><xs:attribute name="visible" type="xs:boolean"></xs:attribute><xs:attribute name="intersect" type="xs:boolean"></xs:attribute></xs:complexType><!-- 		entity element - used for specifying the root element for a fetch, only one root entity is allowed in a given fetch, all others are dependent on this entity and are marked as link-entity	 	--><!-- [XDR-XSD] "entity" element  --><xs:complexType name="FetchEntityType"><xs:choice minOccurs="0" maxOccurs="unbounded"><!-- --><xs:element ref="all-attributes" minOccurs="0" /><xs:element name="attribute" type="FetchAttributeType" minOccurs="0" maxOccurs="unbounded" /><xs:element name="order" type="FetchOrderType" minOccurs="0" maxOccurs="unbounded" /><xs:element name="link-entity" type="FetchLinkEntityType" /><xs:element ref="filter" minOccurs="0" /></xs:choice><!-- --><xs:attribute name="name" use="required" type="xs:string"></xs:attribute></xs:complexType><!-- 		fetch element - root element for the query	 	--><!-- [XDR-XSD] "fetch" element  --><xs:element name="fetch" type="FetchType"/><xs:complexType name="FetchType"><xs:choice minOccurs="0" maxOccurs="unbounded"><!-- --><xs:element name="entity" type="FetchEntityType" /><!-- This is for the Reports view only --><xs:element name="order" type="FetchOrderType" minOccurs="1" maxOccurs="1" /></xs:choice><!-- --><xs:attribute name="version"/><xs:attribute name="count" type="xs:integer"/><xs:attribute name="page" type="xs:integer"/><xs:attribute name="paging-cookie" type="xs:string"/><xs:attribute name="utc-offset" type="IntOrEmpty"/><xs:attribute name="aggregate" type="xs:boolean"/><xs:attribute name="distinct" type="xs:boolean"/><xs:attribute name="top" type="xs:integer"/><xs:attribute name="mapping"><xs:simpleType><xs:restriction base="xs:NMTOKEN"><xs:enumeration value="internal" /><xs:enumeration value="logical" /></xs:restriction></xs:simpleType></xs:attribute><xs:attribute name="min-active-row-version" type="xs:boolean" use="optional" default="false"/><xs:attribute name="output-format"><xs:simpleType><xs:restriction base="xs:NMTOKEN"><xs:enumeration value="xml-ado" /><xs:enumeration value="xml-auto" /><xs:enumeration value="xml-elements" /><xs:enumeration value="xml-raw" /><xs:enumeration value="xml-platform" /></xs:restriction></xs:simpleType></xs:attribute><xs:attribute name="returntotalrecordcount" type="xs:boolean" use="optional" default="false" /><xs:attribute name="no-lock" type="xs:boolean" use="optional" default="false" /></xs:complexType><!-- [XDR-XSD] XDR datatype derivations --><xs:element name="savedquery"><xs:complexType><xs:all><xs:element name="name" type="xs:string" minOccurs="1" maxOccurs="1" /><xs:element name="savedqueryid" type="guid" minOccurs="1" maxOccurs="1" /><xs:element name="returnedtypecode" type="SerializedInteger" minOccurs="1" maxOccurs="1" /><xs:element name="description" type="xs:string" minOccurs="0" maxOccurs="1" /><xs:element name="querytype" type="SerializedInteger" minOccurs="1" maxOccurs="1" /><xs:element name="IsCustomizable" type="SerializedTrueFalse01Type" minOccurs="0" maxOccurs="1" /><xs:element name="CanBeDeleted" type="SerializedTrueFalse01Type" minOccurs="0" maxOccurs="1" /><xs:element name="IntroducedVersion" type="VersionType" minOccurs="0" maxOccurs="1" /><xs:element name="isquickfindquery" type="SerializedTrueFalse01Type" minOccurs="0" maxOccurs="1" /><xs:element name="isuserdefined" type="SerializedTrueFalse01Type" minOccurs="0" maxOccurs="1" /><xs:element name="isdefault" type="SerializedTrueFalse01Type" minOccurs="0" maxOccurs="1" /><xs:element name="isprivate" type="xs:boolean" minOccurs="0" maxOccurs="1" /><xs:element name="queryapi" type="xs:string" minOccurs="0" maxOccurs="1" /><xs:element name="fetchxml" minOccurs="0" maxOccurs="1"><xs:complexType><xs:sequence><xs:element ref="fetch" minOccurs="0" maxOccurs="1" /></xs:sequence></xs:complexType></xs:element><xs:element name="columnsetxml" minOccurs="1" maxOccurs="1"><xs:complexType><xs:sequence><xs:element name="columnset" minOccurs="0" maxOccurs="1"><xs:complexType><xs:choice minOccurs="0" maxOccurs="unbounded"><!-- Because <column> contains text and one attribute we cannot specify its type. We have to define it as a complexType with a simple content. --><xs:element name="column" minOccurs="0" maxOccurs="1"><xs:complexType><xs:simpleContent><xs:extension base="xs:string"><xs:attribute name="build" type="build" /><xs:attribute name="addedby" type="xs:string" /></xs:extension></xs:simpleContent></xs:complexType></xs:element><xs:choice><xs:element name="ascend" minOccurs="0" maxOccurs="1" /><xs:element name="descend" minOccurs="0" maxOccurs="1" /></xs:choice><xs:element name="filter" minOccurs="0" maxOccurs="1"><!-- Allow support for v1.5 format --><xs:complexType><xs:sequence><xs:element name="condition" minOccurs="1" maxOccurs="500"><xs:complexType><xs:attribute name="column" type="xs:string" use="required" /><xs:attribute name="operator" type="operator" use="optional" /><xs:attribute name="value" type="xs:string" use="optional"/></xs:complexType></xs:element></xs:sequence><xs:attribute name="column" type="xs:string" use="optional" /><xs:attribute name="operator" type="operator" use="optional" /><xs:attribute name="value" type="xs:string" use="optional"/><xs:attribute name="type" type="xs:string" use="optional"/></xs:complexType></xs:element></xs:choice><xs:attribute name="version"></xs:attribute><xs:attribute name="distinct" type="xs:boolean"/></xs:complexType></xs:element></xs:sequence></xs:complexType></xs:element><xs:element name="layoutxml" minOccurs="0" maxOccurs="1"><xs:complexType><xs:sequence><xs:element name="grid" minOccurs="0" maxOccurs="1"><xs:complexType><xs:sequence><xs:element name="row" minOccurs="1" maxOccurs="1"><xs:complexType><xs:sequence><xs:element name="cell" minOccurs="1" maxOccurs="unbounded"><xs:complexType><xs:sequence></xs:sequence><xs:attribute name="name" type="xs:string" use="required" /><xs:attribute name="width" type="xs:integer" use="optional" /><xs:attribute name="LabelId" type="xs:string" use="optional" /><xs:attribute name="label" type="xs:string" use="optional" /><xs:attribute name="desc" type="xs:string" use="optional" /><xs:attribute name="ishidden" type="xs:integer" use="optional" /><xs:attribute name="disableSorting" type="xs:integer" use="optional" /><xs:attribute name="disableMetaDataBinding" type="xs:integer" use="optional" /><xs:attribute name="cellType" type ="xs:string" /></xs:complexType></xs:element></xs:sequence><xs:attribute name="name" type="xs:string" use="required" /><xs:attribute name="id" type="xs:string" use="required" /><xs:attribute name="multiobjectidfield" type="xs:string" /><xs:attribute name="layoutstyle" type="xs:string" /></xs:complexType></xs:element></xs:sequence><xs:attribute name="name" type="xs:string" use="required" /><xs:attribute name="select" type="xs:boolean" use="required" /><xs:attribute name="preview" type="BoolOrEmpty" use="required" /><xs:attribute name="icon" type="BoolOrEmpty" use="required" /><xs:attribute name="jump" type="xs:string" use="optional" /><xs:attribute name="object" type="xs:integer" use="required" /><xs:attribute name="disableInlineEditing" type="xs:integer" use="optional" /><xs:attribute name="iconrenderer" type="xs:string" /><xs:attribute name="multilinerows" type="BoolOrEmpty" use="optional" /></xs:complexType></xs:element></xs:sequence></xs:complexType></xs:element></xs:all><xs:attribute name="donotuseinLCID" type="xs:string" use="optional" /><xs:attribute name="useinLCID" type="xs:string" use="optional" /></xs:complexType></xs:element><xs:complexType name="SerializedInteger"><xs:simpleContent><xs:extension base="xs:nonNegativeInteger"><xs:attribute name="formattedvalue" type="xs:string" /></xs:extension></xs:simpleContent></xs:complexType><xs:simpleType name="build"><xs:restriction base="xs:string"><xs:enumeration value="1.504021" /><xs:enumeration value="1.003017" /></xs:restriction></xs:simpleType><xs:simpleType name="operator"><xs:restriction base="xs:NMTOKEN"><xs:enumeration value="eq" /><xs:enumeration value="neq" /><xs:enumeration value="ne" /><xs:enumeration value="gt" /><xs:enumeration value="ge" /><xs:enumeration value="le" /><xs:enumeration value="lt" /><xs:enumeration value="like" /><xs:enumeration value="not-like" /><xs:enumeration value="in" /><xs:enumeration value="not-in" /><xs:enumeration value="between" /><xs:enumeration value="not-between" /><xs:enumeration value="null" /><xs:enumeration value="not-null" /><xs:enumeration value="yesterday" /><xs:enumeration value="today" /><xs:enumeration value="tomorrow" /><xs:enumeration value="last-seven-days" /><xs:enumeration value="next-seven-days" /><xs:enumeration value="last-week" /><xs:enumeration value="this-week" /><xs:enumeration value="next-week" /><xs:enumeration value="last-month" /><xs:enumeration value="this-month" /><xs:enumeration value="next-month" /><xs:enumeration value="on" /><xs:enumeration value="on-or-before" /><xs:enumeration value="on-or-after" /><xs:enumeration value="last-year" /><xs:enumeration value="this-year" /><xs:enumeration value="next-year" /><xs:enumeration value="last-x-hours" /><xs:enumeration value="next-x-hours" /><xs:enumeration value="last-x-days" /><xs:enumeration value="next-x-days" /><xs:enumeration value="last-x-weeks" /><xs:enumeration value="next-x-weeks" /><xs:enumeration value="last-x-months" /><xs:enumeration value="next-x-months" /><xs:enumeration value="olderthan-x-months" /><xs:enumeration value="last-x-years" /><xs:enumeration value="next-x-years" /><xs:enumeration value="eq-userid" /><xs:enumeration value="ne-userid" /><xs:enumeration value="eq-userteams" /><xs:enumeration value="eq-useroruserteams" /><xs:enumeration value="eq-businessid" /><xs:enumeration value="ne-businessid" /><xs:enumeration value="eq-userlanguage" /><xs:enumeration value="this-fiscal-year" /><xs:enumeration value="this-fiscal-period" /><xs:enumeration value="next-fiscal-year" /><xs:enumeration value="next-fiscal-period" /><xs:enumeration value="last-fiscal-year" /><xs:enumeration value="last-fiscal-period" /><xs:enumeration value="last-x-fiscal-years" /><xs:enumeration value="last-x-fiscal-periods" /><xs:enumeration value="next-x-fiscal-years" /><xs:enumeration value="next-x-fiscal-periods" /><xs:enumeration value="in-fiscal-year" /><xs:enumeration value="in-fiscal-period" /><xs:enumeration value="in-fiscal-period-and-year" /><xs:enumeration value="in-or-before-fiscal-period-and-year" /><xs:enumeration value="in-or-after-fiscal-period-and-year" /><xs:enumeration value="begins-with" /><xs:enumeration value="not-begin-with" /><xs:enumeration value="ends-with" /><xs:enumeration value="not-end-with" /></xs:restriction></xs:simpleType><xs:simpleType name="VersionType"><xs:annotation><xs:documentation xml:lang="en">The representation of a Version number.</xs:documentation></xs:annotation><xs:restriction base="xs:string"><xs:pattern value="^[0-9]+(\.[0-9]+){1,3}$" /></xs:restriction></xs:simpleType><xs:simpleType name="guid"><xs:restriction base="xs:string"><xs:pattern value="\{?[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\}?" /></xs:restriction></xs:simpleType><xs:simpleType name="BoolOrEmpty"><xs:union memberTypes="xs:boolean"><xs:simpleType><xs:restriction base="xs:string"><xs:enumeration value="" /></xs:restriction></xs:simpleType></xs:union></xs:simpleType><xs:simpleType name="IntOrEmpty"><xs:union memberTypes="xs:integer"><xs:simpleType><xs:restriction base="xs:string"><xs:enumeration value="" /></xs:restriction></xs:simpleType></xs:union></xs:simpleType><xs:simpleType name="TrueFalse01Type"><xs:restriction base="xs:string"><xs:enumeration value="0" /><xs:enumeration value="1" /></xs:restriction></xs:simpleType><xs:simpleType name="AggregateType"><xs:restriction base="xs:NMTOKEN"><xs:enumeration value="count" /><xs:enumeration value="countcolumn" /><xs:enumeration value="sum" /><xs:enumeration value="avg" /><xs:enumeration value="min" /><xs:enumeration value="max" /></xs:restriction></xs:simpleType><xs:simpleType name="DateGroupingType"><xs:restriction base="xs:NMTOKEN"><xs:enumeration value="day" /><xs:enumeration value="week" /><xs:enumeration value="month" /><xs:enumeration value="quarter" /><xs:enumeration value="year" /><xs:enumeration value="fiscal-period" /><xs:enumeration value="fiscal-year" /></xs:restriction></xs:simpleType><xs:simpleType name="FetchBoolType"><xs:restriction base="xs:NMTOKEN"><xs:enumeration value="true" /><xs:enumeration value="false" /><xs:enumeration value="1" /><xs:enumeration value="0" /></xs:restriction></xs:simpleType><xs:complexType name="SerializedTrueFalse01Type"><xs:simpleContent><xs:extension base="TrueFalse01Type"><xs:attribute name="name" type="xs:string" /></xs:extension></xs:simpleContent></xs:complexType><xs:complexType name="LocalizedNamesType"><xs:sequence><xs:element name="LocalizedName" type="FieldXmlFieldUIType" minOccurs="0" maxOccurs="unbounded" /></xs:sequence></xs:complexType><xs:complexType name="DescriptionsType"><xs:sequence><xs:element name="Description" type="FieldXmlFieldUIType" minOccurs="0" maxOccurs="unbounded" /></xs:sequence></xs:complexType><xs:complexType name="FieldXmlFieldUIType"><xs:attribute name="id" type="guid" /><xs:attribute name="description" use="required" type="xs:string" /><xs:attribute name="languagecode" use="required" type="xs:positiveInteger" /></xs:complexType></xs:schema>';
    
    validator.validateFetchXml = function (fetchXml, schema) {
        if (typeof schema !== 'string' || schema.length === 0) {
            schema = validator.Crm2013Xsd;
        }
        var module = {
            xml: fetchXml,
            schema: schema,
            arguments: ["--noout", "--schema", "CRM 2013 XSD", "FetchXML"]
        };
        return validateXML(module);
    };

		var processResults = function (data) {
			$('#jsonOutput pre').html(formatter.syntaxHighlight(JSON.stringify(data, undefined, 4)));

			// Load table
			writeToTable(data);

			$('.tabular').click();
		};

		var getJCLTemplate = function (fetchQuery, sampleData) {

			// Set Fake
			//var fakeData = JSON.stringify(sampleData).replace(/\"/g, '\\"');

			var output = "" +
				"// Sample Query\n" +
				"var getData = function () {\n" +
				"  " + fetchQuery + "\n\n" +
				"  JCL.fetch(fetchXML, processData);\n" +
				"};\n" +
				"\n" +
				"// Sample Fake \n" +
				"var getFakeData = function () {\n" +
				"  var fake = " + JSON.stringify(sampleData) + ";\n" +
				"  processData(fake);\n" +
				"};\n" +
				"\n" +
				"// Sample Call \n" +
				"var processData = function (data) {\n" +
				"  // handling data\n" +
				"  alert(&#39;Found &#39; + data.length + &#39; record(s).&#39;);\n\n" +
				"  // or something like...\n" +
				"  alert(&#39;Found &#39; + data[0].attributes.yomifullname.value);\n" +
				"};\n" +
				"\n" +
				"// Sample Usage \n" +
				"if (typeof Xrm === 'object') {\n" +
				"  getData();\n" +
				"} else { \n" +
				"  getFakeData();\n" +
				"}";

			return formatter.syntaxHighlightJS(output);
		};

		var isMetaDataLoaded = function (askOnly) {
			var entityList = getListOfEntities(),
				i = 0;

			for (i = 0; i < entityList.length; i++) {
				if (!ft3.attributeList.hasOwnProperty(entityList[i].entity)) {
					if (askOnly) {
						return false;
					} else {
						queryEntityMetadata(entityList[i].entity, false);
					}
				}
			}
			
			return true;
		};

		$(function() {
			$('#btnFetch').on('click', function () {
				var fetch = editor.getValue(),
					jclLines = formatter.formatXMLForJCL(fetch),
					i = 0, 
					lines = jclLines.split('\n'),
					jclCode = "var fetchXML = '' + \n";

				showLoading();

				for(i = 0; i < lines.length - 1; i++) { 
					jclCode += "    '" + lines[i] + "' +\n"; 
				}

				jclCode += "    '" + lines[lines.length-1] + "';";

				// confirm we have all of the metadata for the columns
				if (!isMetaDataLoaded(true)){
					isMetaDataLoaded(false);
				}

				if (typeof Xrm === 'object') {
					JCL.fetch(fetch, function (data) {
						processResults(data);
						$('#jclOutput pre').html(getJCLTemplate(jclCode, data));
						$('.recCount').html(data.length);
						hideLoading();
					});
				} else {
					processResults(fake);
					$('#jclOutput pre').html(getJCLTemplate(jclCode, fake));
					$('.recCount').html(fake.length);
					hideLoading();
				}

				// show output
				//$('#left-nav li.json').click();
			});

			$('#btnBeautify').on('click', function () {
				var fetch = editor.getValue().trim();
				editor.setValue(vkbeautify.xml(fetch));
			});

			$('#btnValidate').on('click', function () {
        		var fetch = editor.getValue().trim();
        		showErrorMessage(500, 'Validation Results', validator.validateFetchXml(fetch));
			});

			// Left Navigation
			$('#left-nav li').on('click', function () {
				var i = 0;

				for (i = 0; i < leftNavItems.length; i++) {
					if ($(this).hasClass(leftNavItems[i])) {
						$('.tab-pane').removeClass('active');
						$('#' + leftNavItems[i]).addClass('active');

						// unselect nav item
						$('#left-nav li').removeClass('selected');
						$(this).addClass('selected');
					}
				}

				// make sure the app size is correct
				resizeApplication();
			});


			$('.icon-close').on('click', function () {
				// Hide Alert/Error message
				$('#error-message').hide();

				// Just in case, hide loading...
				hideLoading();
			});

			JCL._HandleErrors = overrideJCLErrorHandler;

			// fit to page
			resizeApplication();
		});

		var leftNavItems = ['editor', 'codeTab', 'json', 'tabular'];
		var fake = [{
				        "guid": "0d04cc52-f6ee-e211-9fa2-005056b800f8",
				        "logicalName": "contact",
				        "attributes": {
				            "yomifullname": {
				                "type": "c:string",
				                "value": "Paul Way"
				            },
				            "contactid": {
				                "type": "c:guid",
				                "value": "0d04cc52-f6ee-e211-9fa2-005056b800f8"
				            },
				            "familystatuscode": {
				            	"type": "a:OptionSetValue",
				            	"value": 1,
				            	"formattedValue": "Married"
				            },
				            "accountid": {
				            	"type": "a:EntityReference",
				            	"logicalName": "account",
				            	"guid": "0d04cc52-f6ee-e211-9fa2-005056b800f8",
				            	"name": "Test Account"
				            }
				        }
				    }];


		var showLoading = function () {
			$('#load-bg').show();
		};

		var hideLoading = function () {
			$('#load-bg').hide();
		};

		var showErrorMessage = function (statusCode, statusText, errorMessage) {
			// everything should be a status code of 500 (internal server error)
			$('#error-message .title').html(statusText);
			$('#error-message .message').html(errorMessage);
			$('#error-message').show();
		};

		var resizeApplication = function () {
			var appHeight = $(window).height() - $('.title-header').outerHeight();
			$('#left-nav').height(appHeight);
			$('#main').height(appHeight);

			$('.tab-content').height(appHeight - 16);
			editor.setSize('100%', $(window).height() - $('.cm-s-default').position().top - 8);
			$('div#table-output').height($(window).height() - $('div#table-output').position().top - 8);
		};

		$(window).resize(function() {
			resizeApplication();
		});

		var in_array = function (array, val) {
		    for(var i=0; i<array.length; i++) {
		        if (array[i] === val) {
		        	return true;
		        }
		    }
		    return false;
		};

		var getDisplayNameOfColumn = function (field) {
			var entityList = ft3.tableEntityList,
				i = 0,
				fieldList,
				alias = '';

			if (field.indexOf('.') > 0) {
				alias = field.split('.')[0];
				field = field.split('.')[1];

				for (i = 0; i < ft3.tableEntityList.length; i++) {
					if (alias === ft3.tableEntityList[i].alias) {
						if (ft3.entityMetadata.hasOwnProperty(ft3.tableEntityList[i].entity)) {
							fieldList = ft3.entityMetadata[ft3.tableEntityList[i].entity].attributes;
						}
					}
				}

			} else {
				// get first (or root) entity
				if (ft3.entityMetadata.hasOwnProperty(ft3.tableEntityList[0].entity)) {
					fieldList = ft3.entityMetadata[ft3.tableEntityList[0].entity].attributes;
				}
			}

			if (typeof fieldList === 'undefined') {
				// unable to find field/alias combo
				return field;
			}

			for (i = 0; i < fieldList.length; i++) {
				if (fieldList[i].LogicalName === field) {
					return fieldList[i].DisplayName;
				}
			}

			return field;
			//for (i = 0; i < entityList.length; i++) {
			//	if (!ft3.attributeList.hasOwnProperty(entityList[i].entity)) {
		};

		var writeToTable = function (data) {
			var i = 0,
				attrList = [],
				key,
				tblHTML,
				display = '',
				recFields,
				j = 0;

			for (i = 0; i < data.length; i++) {
				for (key in data[i].attributes) {
					if (!in_array(attrList, key)) {
						attrList.push(key);
					}
				}
			}

			tblHtml = "<table><thead>";
			ft3.tableEntityList = getListOfEntities();

			for (i = 0; i < attrList.length; i++) {
				tblHtml += "<th>" + getDisplayNameOfColumn(attrList[i]) + "</th>";
			}

			tblHtml += '</thead><tbody>';


			for (i = 0; i < data.length; i++) {
				tblHtml += '<tr>';
				recFields = Object.keys(data[i].attributes);

				for (j = 0; j < attrList.length; j++) {
					key = attrList[j];

					if (recFields.indexOf(key) >= 0) {
						display = '';
						switch (data[i].attributes[key].type) {
							case 'a:OptionSetValue':
							case 'c:boolean':
								display = '<a href="#" data-toggle="tooltip" title="' + data[i].attributes[key].value + '">' + data[i].attributes[key].formattedValue + '</a>';
								break;
							case 'a:EntityReference':
								display = '<a href="#" data-toggle="tooltip" title="' + data[i].attributes[key].logicalName + ' - ' + data[i].attributes[key].guid + '">' + data[i].attributes[key].name + '</a>';
								break;
							case 'c:dateTime':
							case 'c:decimal':
							case 'a:Money':
								display = data[i].attributes[key].formattedValue;
								break;
							default:
								display = data[i].attributes[key].value;
								break;
						}

						tblHtml += '<td>' + display + '</td>';
					} else {
						// blank column
						tblHtml += '<td class="null">null</td>';
					}					

				}

				tblHtml += '</tr>';
			}			

			tblMain = '</tbody>';

			$('#table-output').html(tblHtml);

			// enable tooltips
			$('[data-toggle="tooltip"]').tooltip();

			// write headers
			return attrList;
		};

		// define a handler
		var shortCutKeys = function (e) {

		    // this would test for whichever key is 40 and the ctrl key at the same time
		    if (e.ctrlKey && e.altKey) {
		    	switch (e.keyCode) {
		    		case 66: // b
						// Beautify
						$('#btnBeautify').click();
						break;

					case 88: // x
						// Execute Fetch
						$('#btnFetch').click();
						break;

					case 69: // e
						$('li.editor').click();
						break;

					case 67: // c
						$('li.codeTab').click();
						break;

					case 74: // j
						$('li.json').click();
						break;

					case 84: // t
						$('li.tabular').click();
						break;

					default:
						break;
			    }
		    }
		};

		var testKey = function (e) {
			console.log(e.keyCode);
		};

		// register the handler 
		document.addEventListener('keyup', shortCutKeys, false);

	</script>
</head>

<body>
	<div class="title-header">
		<span class="title-icon"></span>
		<span class="title-main">Fetch Tester 3000</span>
		<span class="version">Version 0.1.3 Beta</span>
	</div>

	<div id="left-nav">
		<ul>
			<li class="selected editor"><i class="icon editor"></i><a href="#">Editor</a></li>
			<li class="codeTab"><i class="icon code"></i><a href="#">Code</a></li>
			<li class="json"><i class="icon json"></i><a href="#">JSON</a></li>
			<li class="tabular"><i class="icon tabular"></i><a href="#">Tabular</a></li>
		</ul>
	</div>
	<div id="main">


	<div class="tabbable"> <!-- Only required for left/right tabs -->
		<div class="tab-content">
			<div class="tab-pane active" id="editor">
			
				<div class="title-area">
					<!-- Editor Menu -->
					<div class="context-menu">
						<span id="btnFetch" class="btn"><i class="icon execute"></i>Execute Fetch</span>
						<span id="btnBeautify" class="btn"><i class="icon beautify"></i>Beautify</span>
						<span id="btnValidate" class="btn"><i class="icon validate"></i>Validate</span>
					</div>

					<h1>Fetch Editor</h1>
					<h5>Let's start here...</h5>
				</div>

				    <form>
				        <textarea id="code" name="code" rows="20" height="600px"><fetch top="10">
				    <entity name="account">
				        <attribute name="primarycontactid" />
				      <attribute name="lastusedincampaign" />
				        <attribute name="telephone1" />
				        <attribute name="name" />
				        <attribute name="accountid" />
				        <order attribute="name" descending="false" />
				        <filter type="and">
				            <condition attribute="statecode" operator="eq" value="0" />
				        </filter>
				        <link-entity name="contact" from="parentcustomerid" to="accountid" alias="ab">
				          <attribute name="fullname" />
				            <filter type="and">
				              <condition attribute="firstname" operator="like" value="A%" />
				                <condition attribute="lastname" operator="eq" value="Smith" />
				            </filter>
				        </link-entity>
				    </entity>
				</fetch>
				        </textarea>
				    </form>

			</div>
			<div class="tab-pane" id="codeTab">
				<div class="title-area">
					<h1>Generated Scenarios</h1>
					<h5>Leverage your query</h5>
				</div>				
				<div id="jclOutput">
					<div class="info">
						<b>What is this for?</b><br />
						Using <a href="https://github.com/paul-way/JCL" target="_blank">JCL</a> or <a href="https://xrmsvctoolkit.codeplex.com/" target="_blank">other CRM based JavaScript libraries</a>, you can easily query complex data from CRM. Provided below is an example of the fetch in JavaScript as well as some fake data usage.  The sample usage shows an easy way to develop locally versus having to save/publish within CRM.
					</div>
					<pre>

					</pre>
				</div>
			</div>
			<div class="tab-pane" id="json">
				<div class="title-area">
					<h1>JSON View</h1>
					<h5>Result Count: <span class="recCount">?</span></h5>
				</div>					
				<div id="jsonOutput">
					<pre>

					</pre>
				</div>
			</div>
			<div class="tab-pane" id="tabular">
				<div class="title-area">
					<h1>Table View</h1>
					<h5>Result Count: <span class="recCount">?</span></h5>
				</div>					
				<div id="table-output">

				</div>
			</div>
		</div>
	</div>
</div>
	<div id="load-bg">
		<div id="load-content">
			<img src="images/load.gif" />
		</div>
	</div>

	<div id="error-message" style="display:none;">
		<div class="container">
			<span class="icon-alert"></span>
			<span class="icon-close"></span>			
			<span class="error-content">
				<span class="title">Unable to Execute FetchXML</span>
				<span class="message">Some long message</span>
			</span>
		</div>
	</div>
  <script src="script/fetch.js"></script>
</body>
</html>